<?php
/**
 * Request
 * 
 * @package Request
 * @author Shuky
 * @since v1.0
 * @version $Id: Request.php 8 2010-04-03 12:11:43Z shuky $
 */
namespace SFramework;

class Request
{
    // 自身实例，以实现单件模式
    protected static $_instance = null;
    
    // url基础路径
    protected $_baseUrl = null;
    
    // requestUri
    protected $_requestUri;
    
    // scriptUrl
    protected $_scriptUrl = null;
    
    // pathInfo
    protected $_pathInfo = null;
    
    // host
    protected $_hostInfo = null;
	
	
    /**
     * 获取实例
     * @return \SFrame\Request
     */
	public static function getInstance()
	{
		if (null === self::$_instance) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}
	
	
	/**
	 * 获取Request_Uri
	 * 注意：这里没有实现IIS方面的代码
	 * @return string
	 */
	public function getRequestUri()
	{
		if (empty($this->_requestUri)) {
		    $requestUri = $_SERVER['REQUEST_URI'];
		    // Http proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path
		    $schemeAndHost = $this->getHostInfo();
		    if (strpos($requestUri, $schemeAndHost) === 0) {
		        $requestUri = substr($requestUri, strlen($schemeAndHost));
		    }
		    $this->_requestUri = $requestUri;
		}
		return $this->_requestUri;
	}
	
	
	/**
	 * 获取基础url路径
	 * @return string
	 */
	public function getBaseUrl()
	{
		if (null === $this->_baseUrl) {
			$this->_baseUrl = rtrim(dirname($this->getScriptUrl()), '\\/');
		}
		return $this->_baseUrl;
	}
	
	
	/**
	 * 获取url scheme
	 * @return string https|http
	 */
	public function getScheme()
	{
		return (isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on')) ? 'https' : 'http';
	}
	
	
	/**
	 * 获取host
	 * @return string
	 */
	public function getHostInfo()
	{
	    if ($this->_hostInfo == null) {
	        $scheme = $this->getScheme();
    		if (isset($_SERVER['HTTP_HOST'])) {
    			$hostName = $_SERVER['HTTP_HOST'];
    		} else {
    		    $hostName = $_SERVER['SERVER_NAME'];
    		    $port = $_SERVER['SERVER_PORT'];
    		    if (($scheme == 'http' && $port != 80) || ($scheme == 'https') && $port != 443) {
    		    	$hostName = $hostName .':'. $port;
    		    }
    		}
    		$this->_hostInfo = $scheme .'://'. $hostName;
	    }
	    return $this->_hostInfo;
	}
	
	
	/**
	 * 获取脚本的真实路径
	 * @return string
	 */
	public function getScriptUrl()
	{
		if (null === $this->_scriptUrl) {
		    $this->_scriptUrl = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : $_SERVER['PHP_SELF'];
		}
		return $this->_scriptUrl;
	}
	
	
	/**
	 * 获取不带host和scriptUrl相应信息的PATH
	 * @return string
	 */
	public function getPathInfo()
	{
	    if (null === $this->_pathInfo) {
    		$requestUri = $this->getRequestUri();
    		$baseUrl = $this->getBaseUrl();
    		$scriptUrl = $this->getScriptUrl();
    		// Remove the query string from REQUEST_URI
    		if (($pos = strpos($requestUri, '?')) !== false) {
    			$requestUri = substr($requestUri, 0, $pos);
    		}
    		// 如果带有一至的scriptUrl，则去除scriptUrl
    		// 否则去除Host
    		if (strpos($requestUri, $scriptUrl) === 0) {
    			$pathInfo = substr($requestUri, strlen($scriptUrl));
    		} elseif ($baseUrl !== null) {
    		    $pathInfo = substr($requestUri, strlen($baseUrl));
    		} else {
    		    throw new SException\Request('请求检测出错');
    		}
    		// 去除斜杠
    		$pathInfo = trim($pathInfo, '/');
    		// 去除多重无意义的重复性斜杠
    		$this->_pathInfo = preg_replace('/\/+/', '/', $pathInfo);
	    }
	    return $this->_pathInfo;
	}
	
	
	/**
	 * 忽略get和post，获取传递的参数
	 * get优先，然后post，然后默认值
	 * 如果$key为空，则获取全部
	 * @param string $key
	 * @param string $default
	 * @return mixed
	 */
	public function getParam($key = null, $default = null)
	{
	    if (null === $key) {
	    	return $_GET + $_POST;
	    }
		return isset($_GET[$key]) ? $_GET[$key] : (isset($_POST[$key]) ? $_POST[$key] : $default);
	}
	
	
	/**
	 * 按get获取
	 * 如果没有指定键值，则全部获取
	 * @todo 如果是嵌套数组怎么处理
	 * @param string $key
	 * @param mixed $default
	 * @return mixed
	 */
	public function getQuery($key = null, $default = null)
	{
	    if (null === $key) {
	    	return $_GET;
	    }
		return isset($_GET[$key]) ? $_GET[$key] : $default;
	}
	
	
    /**
     * 按post获取
     * 如果没有指定键值，则全部获取
     * @todo 如果是嵌套数组怎么处理
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    public function getPost($key = null, $default = null)
    {
        if (null === $key) {
            return $_POST;
        }
        return isset($_POST[$key]) ? $_POST[$key] : $default;
    }
}
